import moment from 'moment';
import {ElNotification as notification} from 'element-plus'
import {getPlayRule} from './playRules';
import {getAlarmLabel} from '@/utils/consts/alarm';
import {wsSocket} from '@/utils/webSocket';
import {Storage} from '@/utils/storage';
import {ACCESS_TOKEN_KEY} from "@/utils/enums/cache-enum";
import {buildMessageApi} from "@/api/personnel";

const playRules = getPlayRule();
const deviceTypeList = ['four_g_watch', 'nb_watch', 'nb_watch']
let webSocket: any
/* thoroughCloseWebSocket 彻底关闭WebSocket */
let thoroughCloseWebSocket = false;
export const sendRealTimeSocket = async (
  bedRealTimeData: any,
  alarmListData: any = [],
  setError: any,
) => {
  const token = Storage.get(ACCESS_TOKEN_KEY, null);
  // console.log('token', token);
  //获取设备code
  const _getDeviceCode = (deviceList: any, deviceType: any, multiple = true) => {
    if (multiple) {
      return deviceList
        .filter((device: any) => deviceType.includes(device.deviceType))
        .map((i: any) => i.deviceCode);
    } else {
      return (deviceList.find((device: any) => device.deviceType === deviceType) || {}).deviceCode;
    }
  };
  /***
   * 初次请求socket 参数
   * */
  const sendData = {
    type: 'real-time',
    token,
    message: bedRealTimeData.map((_: any) => {
      return {
        bracelet: (
          _.deviceList.find((device: any) => deviceTypeList.includes(device.deviceType)) ||
          {}
        ).deviceCode, //4g | nb 手环只会存在一个
        // index === 8 ? '9ca525d592dd' :
        mattress: _getDeviceCode(_.deviceList, 'mattress', false),
        // mattress: ['9ca525d592d2'],
        drawstringDeviceList: _getDeviceCode(_.deviceList, ['nbiot_alarm', 'burglar_alarm']),
        gasList: _getDeviceCode(_.deviceList, ['nbiot_gas', 'gas']),
        gateMagnetismCodeList: _getDeviceCode(_.deviceList, ['gate_magnetism']),
        olderId: _.id,
        smartLockList: _getDeviceCode(_.deviceList, ['smart_lock']),
        smokeList: _getDeviceCode(_.deviceList, ['nbiot_smoke', 'smoke']),
        infraredList: _getDeviceCode(_.deviceList, ['infrared']),
        floodDeviceList: _getDeviceCode(_.deviceList, ['nbiot_flood', 'flood']),
      };
    }),
  };
  // console.log('sendData', sendData);
  /**
   * 更新设备在离线状态
   *@deviceType 设备类型
   * @curVo 当前类型的socket 对象
   * @curBed 当前床对象
   */
  const setDeviceStatus = (deviceName = '', deviceTypeList: any, curData: any = [], curBed: any) => {
    //更新卡片中设备在离线状态
    const vo = curData.find((_: any) => _.dataType === 1300) as any;
    if (vo) {
      const deviceVoList = curBed.deviceList.filter((_: any) => deviceTypeList.includes(_.deviceType));
      deviceVoList.forEach((device: any) => {
        if (device) {
          //设置设备状况
          device.status = vo.dataValue === '10' ? 'alarm' : 'normal';
        }
        //设备离线将触发报警
        if (vo.dataValue === '10') {
          securityAlarm({custom: true, message: `${deviceName}设备已离线`, curData, curBed});
        }
      })
    }
  };
  /**
   * 更新当前时间
   * */
  const setUpdateTime = ({curBed = {} as any, time = new Date()}) => {
    curBed.updateTime = moment(time).format('hh:mm:ss');
    // console.log(8888, time);
  };
  /**
   * 更新人体体征数据
   * */
  const setSomaticData = ({curData = [], curBed = {} as any}) => {
    if (!curBed) {
      return;
    }
    //心率更新
    const heartRate = curData.find((_: any) => _.dataType === 1004) as any;
    if (heartRate) {
      curBed.somaticData.heartRate = heartRate.dataValue;
      setUpdateTime({curBed, time: heartRate.dataTime});
    }
    //呼吸更新
    const breathe = curData.find((_: any) => _.dataType === 1005) as any;
    if (breathe) {
      curBed.somaticData.breathe = breathe.dataValue;
      setUpdateTime({curBed, time: breathe.dataTime});
    }
    //血氧更新
    const bloodOxygen = curData.find((_: any) => _.dataType === 1120) as any;
    if (bloodOxygen) {
      curBed.somaticData.bloodOxygen = bloodOxygen.dataValue;
      setUpdateTime({curBed, time: bloodOxygen.dataTime});
    }
    //血糖更新
    const bloodSugar = curData.find((_: any) => [1121, 1122].includes(_.dataType)) as any;
    if (bloodSugar) {
      curBed.somaticData.bloodSugar = bloodSugar.dataValue;
      setUpdateTime({curBed, time: bloodSugar.dataTime});
    }
    //血压更新
    const bloodPressure = curData.find((_: any) => _.dataType === 1110) as any;
    if (bloodOxygen) {
      curBed.somaticData.bloodPressure = bloodPressure.dataValue;
      setUpdateTime({curBed, time: bloodPressure.dataTime});
    }
    //体温更新
    const temperature = curData.find((_: any) => _.dataType === 1006) as any;
    if (temperature) {
      curBed.somaticData.temperature = temperature.dataValue;
      setUpdateTime({curBed, time: temperature.dataTime});
    }
  };
  let playStatus = '';
  /**
   * 触发设备报警
   * */
  const securityAlarm = ({
                           message = '',
                           custom = false,
                           curData = {} as any,
                           curBed = {} as any,
                           alarmListData = [] as any,
                         }) => {
    if (!Array.isArray(curData)) {
      return;
    }
    //语音播报
    // alarmTime,
    const _playVoice = async ({alarmListData = null as any, message = null as any}) => {
      notification.warning({
        message: message,
        position: 'bottom-right',
      });
      let playCompleteNum = 0; // 播放完成数量
      const awaitPlay = async () => {
        // console.error('当前需要播放的声音', alarmListData[playCompleteNum]);
        // console.error('声音集合', alarmListData);
        playStatus = 'playing';
        // 当前轮全部播放完成  结束递归 并打开开关 供automaticBroadcast下一次调用
        // || !alarmListData[playCompleteNum]
        if (playCompleteNum === alarmListData.length) {
          // console.log(`playCompleteNum----`, playCompleteNum);
          playStatus = 'playEnd';
          return;
        }
        const status = await playRules(alarmListData[playCompleteNum]);
        if (status) {
          playCompleteNum++;
          // console.log(`playCompleteNum`, playCompleteNum);
        }
        awaitPlay();
      };

      if (!playStatus || playStatus === 'playEnd') {
        awaitPlay();
      }
    };
    //自定义报警  仅提示 无需处理(如：设备离线)
    if (custom === true) {
      // alarmTime: '',
      _playVoice({alarmListData, message});
      return;
    }
    //筛选出 需要报警的数据  ifAlarm=true && alarmList.length > 0
    const alarmData = curData.find(
      (_: any) => _.ifAlarm === true && Array.isArray(_.alarmList) && _.alarmList.length > 0,
    );
    if (alarmData) {
      //卡片变红
      // console.log('alarmData++', alarmData);
      // console.log('alarmData.alarmList', alarmData.alarmList);
      curBed.status = 'alarm';
      // alert('卡片变红');
      //遍历报警最新一条socket报警列表
      alarmData.alarmList.forEach(async ({
                                           alarmType = null as any,
                                           alarmTime = null as any,
                                           alarmValue = null as any,
                                           alarmId = '' as any
                                         }) => {
        // console.error('alarmListData--', alarmData.alarmList);
        //以下仅作为体征报警时 数字标红
        //心率异常
        if (['41', '4'].includes(alarmType)) {
          curBed.somaticData.heartRate = alarmValue;
          setUpdateTime({curBed, time: alarmTime});
          curBed.somaticData.heartRateHigh = true;
          // console.log('心率异常!', curBed.somaticData);
        }
        //呼吸异常
        if (['51', '5'].includes(alarmType)) {
          curBed.somaticData.breathe = alarmValue;
          curBed.somaticData.breatheHigh = true;
          setUpdateTime({curBed, time: alarmTime});
          // console.log('呼吸异常!', curBed.somaticData);
        }
        //体温异常
        if (['61', '6'].includes(alarmType)) {
          curBed.somaticData.temperature = alarmValue;
          curBed.somaticData.temperatureHigh = true;
          setUpdateTime({curBed, time: alarmTime});
          // console.log('体温异常!', curBed.somaticData);
        }
        //血氧异常
        if (['120', '123'].includes(alarmType)) {
          curBed.somaticData.bloodOxygen = alarmValue;
          curBed.somaticData.bloodOxygenHigh = true;
          setUpdateTime({curBed, time: alarmTime});
          // console.log('血氧异常!', curBed.somaticData);
        }
        //血压异常
        if (['110', '111'].includes(alarmType)) {
          curBed.somaticData.bloodPressure = alarmValue;
          curBed.somaticData.bloodPressureHigh = true;
          setUpdateTime({curBed, time: alarmTime});
          // console.log('血压异常!', curBed.somaticData);
        }
        //血糖异常
        if (['121', '122'].includes(alarmType)) {
          curBed.somaticData.bloodSugar = alarmValue;
          curBed.somaticData.bloodSugarHigh = true;
          setUpdateTime({curBed, time: alarmTime});
          // console.log('血糖异常!', curBed.somaticData);
        }
        //进行语音报警↓
        //同一张床 同一个类型的报警在列表只会有一个
        if (!alarmListData?.find((alarm: any) => alarm.bedName === curBed.bedName && alarm.alarmType === alarmType)) {
          // console.error('当前新增报警', { bedName: curBed.bedName, alarmType });
          //请求接口获取报警文字内容
          const {message} = await buildMessageApi({
            language: 'cn', //语言
            alarmType, //预警类型
            startTime: alarmTime, //预警开始时间
            displayName: curBed.older, //人员名称
            alarmValue: alarmValue || undefined, //预警值
          });
          //添加至报警列表
          alarmListData?.push({
            type: 2, //1 长者  2 设备
            bedName: curBed.bedName,
            alarmType,
            alarmTime,
            alarmId,
            deviceCode: alarmData.deviceCode,
            deviceType: alarmData.deviceType,
            lastTime: 0,
            olderName: curBed.older,
            olderId: curBed.id,
            alarmText: message,
            disposed: false, //是否处理过   为真 则置灰
          });

          //播放报警
          if (message) {
            _playVoice({alarmListData, message});
          }
        }
      });
    }
  };
  /**
   * 实时数据socket 处理onmessage数据函数
   * */
  const processRealTimeData = (data: any = {}) => {
    //数据规则
    //dataType:1300(在离线)    dataValue: 11 (在线)   10 (离线)
    //dataType:1301(在离床)    dataValue: 12 (在床)   9 (离床)
    //dataType:80(体动)    dataValue: ''    状态类 不关注值
    //dataType:1004(心率)    dataValue: 具体值
    //dataType:1005(呼吸)    dataValue: 具体值
    //dataType:1006(体温)    dataValue: 具体值
    //dataType:1110(血压)    dataValue: 具体值
    //dataType:1121(血糖)    dataValue: 具体值
    //dataType:1120(血氧)    dataValue: 具体值
    //dataType:1200(记步)    dataValue: 具体值
    //dataType:7010(打鼾)    dataValue: 1：有 0：无
    //dataType:1201(位置（经纬度）)    dataValue: 具体值
    //dataType:1202(信号强度)    dataValue: 具体值
    //dataType:1203(电量值)    dataValue: 具体值
    //<--手环-->
    //dataType:7000(正常佩戴)    dataValue: ''    状态类 不关注值
    //dataType:7001(未佩戴)    dataValue: ''    状态类 不关注值
    //dataType:7002[1300 - 10](手环关机（离线）)    dataValue: ''    状态类 不关注值
    //dataType:7003[1300 - 11](手环在线)    dataValue: ''    状态类 不关注值
    //<--安防设备-->
    //dataType:1300(在离线)    dataValue: 11 (在线)   10 (离线)
    //<--安防设备 报警-->
    //dataType:60(烟雾报警)    状态类 不关注值
    //dataType:384(低压报警)    状态类 不关注值
    //dataType:50(燃气报警)    状态类 不关注值
    //dataType:989(门打开)    状态类 不关注值
    //dataType:988(门关闭)    状态类 不关注值
    //dataType:40(水浸报警)    状态类 不关注值
    //dataType:963(防拆报警)    状态类 不关注值
    //dataType:962(报警恢复正常)    状态类 不关注值
    //dataType:30(紧急报警)    状态类 不关注值
    //dataType:940(红外低压)    状态类 不关注值
    //dataType:939(红外离线)    状态类 不关注值
    //dataType:941(红外报警)    状态类 不关注值
    //dataType:935(探测区域已无人)    状态类 不关注值
    //dataType:936(探测区域有人)    状态类 不关注值
    //dataType:7006(电源故障)    状态类 不关注值
    //dataType:7007(电源恢复正常)    状态类 不关注值
    //<--报警-->
    //dataType:4(心率偏低)     状态类 不关注值
    //dataType:41(心率偏高)     状态类 不关注值
    //dataType:5(呼吸偏低)     状态类 不关注值
    //dataType:51(呼吸偏高)     状态类 不关注值
    //dataType:6(体温偏低)     状态类 不关注值
    //dataType:61(体温偏高)     状态类 不关注值
    //dataType:1(翻身报警)     状态类 不关注值
    //dataType:3(尿失禁报警)     状态类 不关注值
    //dataType:70(坠床预警)     状态类 不关注值
    //dataType:71(坐床边)     状态类 不关注值
    //dataType:90(恢复正常)     状态类 不关注值
    //dataType:103(紧急异常)     状态类 不关注值
    //dataType:110(低血压报警)      dataValue: 具体值
    //dataType:111(高血压报警)     dataValue: 具体值
    //dataType:121(低血糖)     dataValue: 具体值
    //dataType:122(高血糖)      dataValue: 具体值
    //dataType:120(低血氧)      dataValue: 具体值
    //dataType:123(高血氧)      dataValue: 具体值
    //dataType:30(SOS报警)       状态类 不关注值
    //dataType:1030(电子围栏)       状态类 不关注值

    //整体判断顺序：
    //灰色：离线
    //红色：所有安防报警 心率报警 呼吸报警 体温报警 血氧报警 血压报警 血糖报警 尿失禁报警 体动报警 在床无心率或呼吸报警
    //黄色 ：不在床/离床  在床边  坐床上
    //蓝色：正常
    //根据老人id 找到相应数据 进行修改
    const curBed = bedRealTimeData.find((_: any) => _.id === data.olderId);
    // console.log('数据---', data);
    // ['mattressData','temperatureData','sugarData','pressureData','drawstringData','floodData','gasData','smokeData','magnetismData','infraredData',]
    Object.keys(data).forEach((key) => {
      // console.log('当前床', curBed);
      // data[key]
      /**
       * 床垫
       * */
      if (key === 'mattressData') {
        //清空体征数组
        curBed.exceptions = [];
        // console.log('床垫数据', data[key]);
        // console.log('总数据', bedRealTimeData);
        //判断是否离线(灰色)
        if (data[key].find((_: any) => _.dataType === 1300 && _.dataValue === '10')) {
          //床垫离线
          curBed.status = 'offline';
        }
        if (data[key].find((_: any) => _.dataType === 1300 && _.dataValue === '11')) {
          //床垫在线
          curBed.status = 'normal';
        }
        /**
         * 判断翻身报警(前置条件： 必须在床)
         * */
        if (data[key].find((_: any) => _.dataType === 1301 && _.dataValue === '12')) {
          const rollOverTimeVo = data[key].find((_: any) => _.dataType === 1);
          if (rollOverTimeVo && rollOverTimeVo.dataValue) {
            const countdown = moment(rollOverTimeVo.dataTime)
              .add({minutes: rollOverTimeVo.dataValue})
              .valueOf();
            curBed.rollOverTime = moment(countdown - moment().valueOf()).format('hh:mm:ss');
            // console.log(7666611, rollOverTimeVo.dataValue);
            // console.log(76666, curBed.rollOverTime);
          }
        }
        /**
         * 判断是报警(黄色)
         * */
        //判断离床/不在床
        if (data[key].find((_: any) => _.dataType === 1301 && _.dataValue === '9')) {
          //卡片变为黄色
          curBed.status = 'warn';
          // alert('卡片变黄');
          curBed.exceptions?.push({name: '离床', state: 'warn'});
        }
        //判断坐床边
        if (data[key].find((_: any) => _.dataType === 71)) {
          //卡片变为黄色
          curBed.status = 'warn';
        }
        /**
         * 体征状态标签   3：失禁， 80：体动， 7010：打鼾
         * */
        const exceptions = data[key].filter((_: any) => [3, 80, 7010].includes(_.dataType));
        if (exceptions?.length > 0) {
          //卡片变为黄色
          curBed.exceptions = curBed.exceptions?.concat(
            exceptions?.map((_: any) => {
              return {name: getAlarmLabel(_.dataType), state: 'alarm'};
            }),
          );
        }
        /**
         * 人体数据更新(心率，血氧，呼吸)
         * */
        setSomaticData({curData: data[key], curBed});
      }
      /**
       * 体温
       * */
      if (key === 'temperatureData') {
        const temperatureData = data[key].find((_: any) => _.dataType === 1006);
        if (temperatureData) {
          curBed.somaticData.temperature = temperatureData.dataValue;
        }
      }
      /**
       * 血糖数据
       * */
      if (key === 'sugarData') {
        // console.log('血糖数据', data[key]);
      }
      /**
       * 血压数据
       * */
      if (key === 'pressureData') {
        const {dataValue} = data[key].find((_: any) => _.dataType === 1110) || {};
        // console.log('血压数据', dataValue);
        curBed.somaticData.bloodPressure = dataValue;
      }
      /**
       * 拉绳数据
       * */
      if (key === 'drawstringData') {
        // console.log('拉绳数据', data[key]);
        //更新拉绳设备在离线状态
        setDeviceStatus('拉绳', ['nbiot_alarm', 'burglar_alarm'], data[key], curBed);
      }
      /**
       * 水浸数据
       * */
      if (key === 'floodData') {
        // console.log('水浸数据', data[key]);
        //更新水浸设备在离线状态
        setDeviceStatus('水浸', ['nbiot_flood', 'flood'], data[key], curBed);
      }
      /**
       * 气感数据
       * */
      if (key === 'gasData') {
        // console.log('气感数据', data[key]);
        setDeviceStatus('气感', ['nbiot_gas', 'gas'], data[key], curBed);
      }
      /**
       * 烟感数据
       * */
      if (key === 'smokeData') {
        // console.log('烟感数据', data[key]);
        //更新烟感数据在离线状态
        setDeviceStatus('烟感', ['nbiot_smoke', 'smoke'], data[key], curBed);
      }
      /**
       * 门磁数据
       * */
      if (key === 'magnetismData') {
        // console.log('门磁数据', data[key]);
        //更新门磁数据在离线状态
        setDeviceStatus('门磁', ['gate_magnetism'], data[key], curBed);
      }
      /**
       * 红外数据
       * */
      if (key === 'infraredData') {
        setDeviceStatus('门磁', ['infrared'], data[key], curBed);
      }
      /**
       * 手环（4G/NB手环）数据
       */
      if (key === 'braceletData') {
        // console.log('手环（4G/NB手环）数据', data[key]);
        //更新门磁数据在离线状态
        setDeviceStatus('手环', deviceTypeList, data[key], curBed);
        /**
         * 人体数据更新(心率，血氧，呼吸)
         * */
        setSomaticData({curData: data[key], curBed});
      }
      /**
       * 智能锁数据
       * */
      if (key === 'smartData') {
        // console.log('智能锁数据', data[key]);
      }
      //触发设备报警
      securityAlarm({curData: data[key], curBed, alarmListData});
    });
  };
  const params = {
    onOpen: () => {
      webSocket.sendMessage(sendData);
    },
    onMessage: (data: any) => {
      setError(false);
      if (!data || data.type === 'heartbeat') {
        return false;
      }
      //处理socket实时数据
      processRealTimeData(data);
    },
    onError() {
      console.log('连接错误');
      setError(true);
    },
  };

  // 创建参数
  webSocket = wsSocket(params);
};

export const closeWebSocket = (thoroughClose = false) => {
  if (webSocket) {
    /* 如果外部选择彻底关闭 改变本文件的彻底关闭webSocket的值为true */
    if (thoroughClose) {
      thoroughCloseWebSocket = true;
    }
    webSocket.destroy();
  }
};
